{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# [Modules and packages](https://docs.python.org/3/tutorial/modules.html#modules)\n",
    "\n",
    "> Module is a Python source code file, i.e. a file with .py extension.\n",
    "\n",
    "> Package is a directory which contains `__init__.py` file and can contain python modules and other packages.  \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Why to organize your code into modules and packages\n",
    "* Maintainability\n",
    "* Reusability\n",
    "* Namespacing\n",
    "* People unfamiliar with your project can get a clear overview just by looking at the directory structure of your project\n",
    "* Searching for certain functionality or class is easy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## How to use\n",
    "\n",
    "Let's use the following directory structure as an example:\n",
    "\n",
    "      \n",
    "```\n",
    "food_store/\n",
    "    __init__.py\n",
    "    \n",
    "    product/\n",
    "        __init__.py\n",
    "        \n",
    "        fruit/\n",
    "            __init__.py\n",
    "            apple.py\n",
    "            banana.py\n",
    "            \n",
    "        drink/\n",
    "            __init__.py\n",
    "            juice.py\n",
    "            milk.py\n",
    "            beer.py\n",
    "\n",
    "    cashier/\n",
    "        __ini__.py\n",
    "        receipt.py\n",
    "        calculator.py\n",
    "```\n",
    "\n",
    "\n",
    "Let's consider that banana.py file contains:\n",
    "\n",
    "```python\n",
    "\n",
    "def get_available_brands():\n",
    "    return [\"chiquita\"]\n",
    "\n",
    "\n",
    "class Banana:\n",
    "    def __init__(self, brand=\"chiquita\"):\n",
    "        if brand not in get_available_brands():\n",
    "            raise ValueError(f\"Unknown brand: {brand}\")\n",
    "        self._brand = brand\n",
    "     \n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Importing\n",
    "\n",
    "Let's say that we need access `Banana` class from banana.py file inside receipt.py. We can achive this by importing at the beginning of receipt.py:\n",
    "\n",
    "```python\n",
    "from food_store.product.fruit.banana import Banana\n",
    "\n",
    "# then it's used like this\n",
    "my_banana = Banana()\n",
    "```\n",
    "\n",
    "\n",
    "\n",
    "If we need to access multiple classes or functions from banana.py file:\n",
    "\n",
    "```python\n",
    "from food_store.product.fruit import banana\n",
    "\n",
    "# then it's used like this\n",
    "brands = banana.get_available_brands()\n",
    "my_banana = banana.Banana()\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A comprehensive introduction to modules and packages can be found [here](https://realpython.com/python-modules-packages/)."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
